package org.rency.ues.engine.service.impl;

import org.apache.commons.lang.StringUtils;
import org.rency.common.utils.security.Base64Utils;
import org.rency.common.utils.security.X509CertDomain;
import org.rency.common.utils.security.X509CertUtils;
import org.rency.ues.common.UesDict;
import org.rency.ues.common.enums.EncryptType;
import org.rency.ues.domain.model.CertificationDomain;
import org.rency.ues.domain.request.CreateCertificationRequest;
import org.rency.ues.domain.response.CreateCertificationResponse;
import org.rency.ues.domain.support.Certification;
import org.rency.ues.engine.converter.CertificationConverter;
import org.rency.ues.engine.manager.CertificationManager;
import org.rency.ues.engine.repository.CertificationRepository;
import org.rency.ues.engine.repository.UesSequenceRepository;
import org.rency.ues.engine.service.CertificationService;
import org.rency.ues.engine.validator.RequestValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.cert.X509Certificate;
import java.util.Date;

/**
 * $TODO
 *
 * @author: Created by user_rcy@163.com on 2016/07/31.
 * @version: V1.0.0
 * @since JDK 1.8
 */
public class CertificationServiceImpl implements CertificationService {

    private static final Logger logger = LoggerFactory.getLogger(CertificationServiceImpl.class);

    private RequestValidator<CreateCertificationRequest, CreateCertificationResponse>  createCertificationRequestValidator;

    private UesSequenceRepository             uesSequenceRepository;

    private CertificationRepository           certificationRepository;

    private CertificationManager              certificationManager;

    @Override
    public CreateCertificationResponse create(CreateCertificationRequest request) {
        logger.info("创建证书请求.{}.",request);
        CreateCertificationResponse response = createCertificationRequestValidator.validator(request);
        if(!response.isSuccess()){
            return response;
        }
        CertificationDomain orgiCertificationDomain = certificationRepository.getByEmail(request.getOrgiEmail());
        if(orgiCertificationDomain != null){
            response.setCertId(orgiCertificationDomain.getId());
            response.setSerialNo(orgiCertificationDomain.getSerialNo());
            logger.info("创建证书已存在[{}],直接返回:{}.",request.getOrgiEmail(),response);
            return response;
        }
        Long serialNo = uesSequenceRepository.getSerialSequence();
        X509CertDomain x509CertDomain = CertificationConverter.build(request,serialNo);
        try{
            byte[] certificationByteArray = X509CertUtils.createX509CertForPfxFileByte(x509CertDomain);
            if(certificationByteArray == null){
                logger.info("创建证书失败,创建证书Byte返回空.");
                return CreateCertificationResponse.fail(UesDict.CHINESE_FAIL_MSG);
            }
            CertificationDomain domain = this.build(certificationByteArray,x509CertDomain);
            boolean result = certificationRepository.save(domain);
            if(result){
                response.setCertId(domain.getId());
                response.setSerialNo(domain.getSerialNo());
                logger.info("创建证书成功,{}.",response);
                return response;
            }
            logger.info("创建证书失败");
            return CreateCertificationResponse.fail(UesDict.CHINESE_FAIL_MSG);
        }catch (Exception e){
            logger.error("创建证书异常,原始请求:{}.",request,e);
            return CreateCertificationResponse.fail(UesDict.CHINESE_FAIL_MSG);
        }
    }

    @Override
    public X509Certificate getX509Certification(String serialNo) {
        Certification cert = this.getCertification(serialNo);
        if(cert == null){
            return null;
        }
        return cert.getCertificate();
    }

    @Override
    public Certification getCertification(String serialNo) {
        logger.debug("获取X509证书,序列号:{}.",serialNo);
        if(StringUtils.isBlank(serialNo)){
            serialNo = certificationManager.getLastedSerialNo();
        }
        return certificationManager.getCertification(serialNo);
    }

    private CertificationDomain build(byte[] certificationByteArray,X509CertDomain x509CertDomain){
        CertificationDomain domain = new CertificationDomain();
        domain.setUpdateTime(new Date());
        domain.setCreateTime(new Date());
        domain.setSerialNo(x509CertDomain.getSerialNumber()+"");
        domain.setCertPassword(x509CertDomain.getPassword());
        domain.setCert(Base64Utils.encodeBase64(certificationByteArray));
        domain.setCertType(EncryptType.RSA);
        return domain;
    }

    public void setCreateCertificationRequestValidator(RequestValidator<CreateCertificationRequest, CreateCertificationResponse> createCertificationRequestValidator) {
        this.createCertificationRequestValidator = createCertificationRequestValidator;
    }

    public void setUesSequenceRepository(UesSequenceRepository uesSequenceRepository) {
        this.uesSequenceRepository = uesSequenceRepository;
    }

    public void setCertificationRepository(CertificationRepository certificationRepository) {
        this.certificationRepository = certificationRepository;
    }

    public void setCertificationManager(CertificationManager certificationManager) {
        this.certificationManager = certificationManager;
    }
}
